package coreconcurrency.unsafe;

import coreconcurrency.entity.Account;
import coreconcurrency.entity.SafeAccount;
import coreconcurrency.entity.UnsafeAccount;

/**
 * create by yongli on 2021-11-27 16:16
 * 银行业务，使用多线程来调度用户的账号
 * 首先要创建多个线程
 * 线程也是一个对象，线程要和业务进行关联
 * 而不是线程可以调用任何的业务，
 * 业务一定是可以被线程调度的。
 */

public class BankService {

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            test(UnsafeAccount.class);
            System.out.println("------safe-------");
            test(SafeAccount.class);
        }
    }

    // 泛型方法
    public static <T extends Account> void test(Class<T> clazz) {
        // 更加用户的提供的类型，创建相关的类
        Account account;
        try {
            account = clazz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
            // 直接抛出运行时异常
            throw new RuntimeException();
        }
        account.setNumber(0);
        // 一个线程调
        for (int i = 0; i < 100; i++) {
            AccountOperation.increment(account);
        }
        System.out.println(account.getNumber());


        Thread[] threads = new Thread[100];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(new Runnable() {
                @Override
                public void run() {
                    // 没有改变对象应用，但是修改了对象的状态,lamda的参数是final修饰
                    try {
                        AccountOperation.increment(account);
                        // 中间发生了线程切换，就会出现不一致
                        Thread.sleep(100);
                        AccountOperation.increment(account);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        for (int i = 0; i < 100; i++) {
            // 开启线程调度
            threads[i].start();
        }

        // 等待所有线程执行完毕
        while (true) {
            int count = 0;
            for (int i = 0; i < 100; i++) {
                if (!threads[i].isAlive()) {
                    count++;
                }
            }
            if (count == 100) {
                break;
            }
        }
        System.out.println(account.getNumber());
    }

    public static void test2(Class<? extends Account> clazz) {

    }
}